home *** CD-ROM | disk | FTP | other *** search
/ Workbench Design / WB Collection.iso / datatypes / debox_dt / source / dispatch.c < prev    next >
C/C++ Source or Header  |  1996-04-07  |  11KB  |  462 lines

  1.  
  2. /******************************************************************************
  3.  *
  4.  * Flowerpower's DeBox Datatype
  5.  *
  6.  * Written by Christian Buchner and David N. Junod
  7.  *
  8.  ******************************************************************************
  9.  * dispatch.c
  10.  *
  11.  * Sorry for Spaghetti code ;-)
  12.  */
  13.  
  14. #include "classbase.h"
  15.  
  16. /*****************************************************************************/
  17.  
  18. #include <stdarg.h>
  19.  
  20. /* Message request routine */
  21.  
  22. void __stdargs Message(struct ClassBase *cb, UBYTE *Msg,...)
  23. {
  24.     va_list Arg;
  25.     struct EasyStruct Req={sizeof(struct EasyStruct),0,"DeBox Request",0,"Okay"};
  26.     va_start(Arg,Msg);
  27.     Req.es_TextFormat=Msg;
  28.     EasyRequestArgs(NULL,&Req,0,Arg);
  29.     va_end(Arg);
  30. }
  31.  
  32. /*****************************************************************************/
  33.  
  34. ULONG setdtattrs (struct ClassBase * cb, Object * o, ULONG data,...)
  35. {
  36.     return (SetDTAttrsA (o, NULL, NULL, (struct TagItem *) & data));
  37. }
  38.  
  39. /*****************************************************************************/
  40.  
  41. ULONG getdtattrs (struct ClassBase * cb, Object * o, ULONG data,...)
  42. {
  43.     return (GetDTAttrsA (o, (struct TagItem *) & data));
  44. }
  45.  
  46. /*****************************************************************************/
  47.  
  48. Class *initClass (struct ClassBase * cb)
  49. {
  50.     Class *cl;
  51.     
  52.     /* Create our class.  Note that this particular class doesn't have any instance data */
  53.     if (cl = MakeClass (LibName, PICTUREDTCLASS, NULL, NULL, 0L))
  54.     {
  55.         cl->cl_Dispatcher.h_Entry = (ULONG (*)())Dispatch;
  56.         cl->cl_UserData = (ULONG) cb;
  57.         AddClass (cl);
  58.     }
  59.     
  60.     return (cl);
  61. }
  62.  
  63. /*****************************************************************************/
  64.  
  65. ULONG __asm Dispatch (register __a0 Class * cl, register __a2 Object * o, register __a1 Msg msg)
  66. {
  67.     struct ClassBase *cb = (struct ClassBase *) cl->cl_UserData;
  68.     ULONG retval;
  69.     
  70.     switch (msg->MethodID)
  71.     {
  72.         case OM_NEW:
  73.         if (retval = DoSuperMethodA (cl, o, msg))
  74.         {
  75.             if (!GetPicture (cb, cl, (Object *) retval, ((struct opSet *) msg)->ops_AttrList))
  76.             {
  77.                 CoerceMethod (cl, (Object *) retval, OM_DISPOSE);
  78.                 return NULL;
  79.             }
  80.         }
  81.         break;
  82.         
  83.         /* Let the superclass handle everything else */
  84.         default:
  85.         retval = (ULONG) DoSuperMethodA (cl, o, msg);
  86.         break;
  87.     }
  88.     
  89.     return (retval);
  90. }
  91.  
  92. /*****************************************************************************/
  93.  
  94. BOOL __asm GetPicture (register __a6 struct ClassBase * cb, register __a0 Class * cl, register __a2 Object * o, register __a1 struct TagItem * attrs)
  95. {
  96.     BOOL Success = TRUE;
  97.     STRPTR title;
  98.     BPTR fh;
  99.     struct BitMapHeader *bmhd;
  100.     struct DeBoxChunk chunk;
  101.     UBYTE *image;
  102.     ULONG imagesize;
  103.     struct BitMap *bm=NULL;
  104.     ULONG modeid;
  105.     
  106.     /* Get the default title */
  107.     title = (STRPTR) GetTagData (DTA_Name, NULL, attrs);
  108.     
  109.     /* Get the file handle to read from and the BitMapHeader to write to */
  110.     if (!((getdtattrs (cb, o, DTA_Handle, &fh, PDTA_BitMapHeader, &bmhd, TAG_DONE) == 2) && fh))
  111.     {
  112.         SetIoErr(ERROR_OBJECT_WRONG_TYPE);
  113.         Success=FALSE;
  114.     }
  115.     else
  116.     {
  117.         /* Seek to the beginning of the file */
  118.         Seek (fh, 0, OFFSET_BEGINNING);
  119.         
  120.         /* Read in the first chunk header (similar to FORM header) */
  121.         if (Read(fh, &chunk, sizeof(chunk))!=sizeof(chunk))
  122.         {
  123.             SetIoErr(ERROR_BAD_HUNK);
  124.             Success=FALSE;
  125.         }
  126.         else
  127.         {
  128.             /* Check header CRC */
  129.             if (!DeBoxCRC(&chunk))
  130.             {
  131.                 SetIoErr(ERROR_BAD_HUNK);
  132.                 Success=FALSE;
  133.             }
  134.             else
  135.             {
  136.                 /* Read out the image size (=chunk size) */
  137.                 imagesize=chunk.chunk_len;
  138.                 
  139.                 /* Allocate space for compressed image data */
  140.                 if (!(image=AllocVec(imagesize,MEMF_PUBLIC)))
  141.                 {
  142.                     SetIoErr(ERROR_NO_FREE_STORE);
  143.                     Success=FALSE;
  144.                 }
  145.                 else
  146.                 {
  147.                     /* Read compressed image data */
  148.                     if (Read(fh, image, imagesize)!=imagesize)
  149.                     {
  150.                         SetIoErr(ERROR_BAD_HUNK);
  151.                         Success=FALSE;
  152.                     }
  153.                     else
  154.                     {
  155.                         /* Decompress image data, create a Bitmap */
  156.                         Success=DecrunchBitmap(cb,o,image,imagesize,&bm,bmhd,&modeid);
  157.                     }
  158.                     /* Compressed data is no longer needed */
  159.                     FreeVec(image);
  160.                 }
  161.             }
  162.         }
  163.     }
  164.     if (Success)
  165.     {
  166.         if (bm)
  167.         {
  168.             /* Set the attributes */
  169.             setdtattrs (cb, o,
  170.                 DTA_ObjName,        title,
  171.                 DTA_NominalHoriz,    bmhd->bmh_Width,
  172.                 DTA_NominalVert,    bmhd->bmh_Height,
  173.                 PDTA_BitMap,        bm,
  174.                 PDTA_ModeID,        modeid,
  175.                 TAG_DONE);
  176.         }
  177.     }
  178.     else
  179.     {
  180.         /* On failure, just free the BitMap */
  181.         if (bm) FreeBitMap(bm);
  182.     }
  183.     return(Success);
  184. }
  185.  
  186.  
  187. BOOL DecrunchBitmap(struct ClassBase *cb, Object *o, UBYTE *buffer, ULONG size, struct BitMap **bm, struct BitMapHeader *bmhd, ULONG *modeid)
  188. {
  189.     BOOL Success=TRUE;
  190.     struct DeBoxChunk *chunk;
  191.     UBYTE *data;
  192.     UWORD n;
  193.     UWORD *colors;
  194.     struct ColorRegister *cmap;
  195.     LONG *cregs;
  196.     UBYTE *sourcedata;
  197.     ULONG sourcesize;
  198.     UBYTE *destindata;
  199.     ULONG destinsize;
  200.     UBYTE *referencedata;
  201.     BOOL Extra=FALSE;
  202.     
  203.     /* loop through chunks */
  204.     for (    chunk=(struct DeBoxChunk*)buffer ;
  205.             Success && ((UBYTE*)(chunk)<(buffer+size)) ;
  206.             chunk=(struct DeBoxChunk*)((UBYTE*)(chunk+1)+chunk->chunk_len)    )
  207.     {
  208.         /* Check header CRC */
  209.         if (!DeBoxCRC(chunk))
  210.         {
  211.             SetIoErr(ERROR_BAD_HUNK);
  212.             Success=FALSE;
  213.             break;
  214.         }
  215.         else
  216.         {
  217.             /* set data start address */
  218.             data=(UBYTE*)(chunk+1);
  219.             
  220. //            Message(cb,    "Read chunk: %ld (%ld)\n"
  221. //                        "Checksum: $%02lx\n"
  222. //                        "HeaderMark: $%02lx\n"
  223. //                        "DontKnow_02: $%04lx\n"
  224. //                        "Flags: $%02lx\n"
  225. //                        "CrunchMethod: $%02lx\n"
  226. //                        "Destination Plane: $%02lx\n"
  227. //                        "Reference Plane: $%02lx",
  228. //                        
  229. //                        chunk->chunk_len,
  230. //                        chunk->decrunched_len,
  231. //                        (ULONG)chunk->checksum,
  232. //                        (ULONG)chunk->headermark,
  233. //                        (ULONG)chunk->dontknow02,
  234. //                        (ULONG)chunk->flags,
  235. //                        (ULONG)chunk->crunchmethod,
  236. //                        (ULONG)chunk->destinplane,
  237. //                        (ULONG)chunk->referenceplane);
  238.             
  239.             /* Init pointers */
  240.             sourcedata=data;
  241.             
  242.             /* Get (corrected) size of chunk */
  243.             sourcesize=chunk->chunk_len;
  244.             if (chunk->flags&FLGF_SUBTRACT_ONE_BYTE) sourcesize--;
  245.             
  246.             /* Get size of destination buffer */
  247.             destinsize=chunk->decrunched_len;
  248.             
  249.             if (chunk->flags&FLGF_USE_EXTRA_BUFFER)
  250.             {
  251.                 /* Allocate an extra buffer */
  252.                 destinsize=*((ULONG*)sourcedata);
  253.                 sourcesize-=sizeof(ULONG);
  254.                 sourcedata+=sizeof(ULONG);
  255.                 if (!(destindata=AllocVec(destinsize,MEMF_CLEAR)))
  256.                 {
  257.                     Message(cb,"No memory for extra buffer!");
  258.                     SetIoErr(ERROR_NO_FREE_STORE);
  259.                     Success=FALSE;
  260.                     break;
  261.                 }
  262.                 Extra=TRUE;
  263.             }
  264.             else
  265.             {
  266.                 /* See if we already have a bitmap */
  267.                 if (*bm==NULL)
  268.                 {
  269.                     /* No: Allocate storage for DeBoxInfo structure */
  270.                     /* (this structure may be crunched) */
  271.                     if (!(destindata=AllocVec(destinsize,MEMF_PUBLIC)))
  272.                     {
  273.                         SetIoErr(ERROR_NO_FREE_STORE);
  274.                         Success=FALSE;
  275.                         break;
  276.                     }
  277.                     Extra=TRUE;
  278.                 }
  279.                 else
  280.                 {
  281.                     /* No extra buffer, bitmap exists */
  282.                     /* so check and get destination plane */
  283.                     if (chunk->destinplane>=bmhd->bmh_Depth)
  284.                     {
  285.                         SetIoErr(ERROR_BAD_HUNK);
  286.                         Success=FALSE;
  287.                         break;
  288.                     }
  289.                     destindata=(*bm)->Planes[chunk->destinplane];
  290.                 }
  291.             }
  292.             
  293.             /* Check and get reference plane */
  294.             if (*bm)
  295.             {
  296.                 if (chunk->referenceplane>=bmhd->bmh_Depth)
  297.                 {
  298.                     SetIoErr(ERROR_BAD_HUNK);
  299.                     Success=FALSE;
  300.                     break;
  301.                 }
  302.                 referencedata=(*bm)->Planes[chunk->referenceplane];
  303.             }
  304.             else
  305.             {
  306.                 referencedata=NULL;
  307.             }
  308.             
  309.             /* Handle the different crunch methods */
  310.             switch(chunk->crunchmethod)
  311.             {
  312.                 case CRUNCHMETHOD_PLAIN:
  313.                 {
  314.                     CopyMem(sourcedata,destindata,destinsize);
  315.                     break;
  316.                 }
  317.                 case CRUNCHMETHOD_1:
  318.                 {
  319.                     Method_1(sourcedata,sourcesize,referencedata,destindata,destinsize);
  320.                     break;
  321.                 }
  322.                 case CRUNCHMETHOD_2:
  323.                 {
  324.                     Method_2(sourcedata,sourcesize,referencedata,destindata,destinsize);
  325.                     break;
  326.                 }
  327.                 case CRUNCHMETHOD_FILL:
  328.                 {
  329.                     if (sourcesize!=1)
  330.                     {
  331.                         SetIoErr(ERROR_BAD_HUNK);
  332.                         Success=FALSE;
  333.                         break;
  334.                     }
  335.                     else
  336.                     {
  337.                         memset(destindata,destinsize,*sourcedata);
  338.                     }
  339.                     break;
  340.                 }
  341.                 case CRUNCHMETHOD_4:
  342.                 {
  343.                     Method_4(sourcedata,sourcesize,referencedata,destindata,destinsize);
  344.                     break;
  345.                 }
  346.                 case CRUNCHMETHOD_5:
  347.                 {
  348.                     Method_5(sourcedata,sourcesize,referencedata,destindata,destinsize);
  349.                     break;
  350.                 }
  351.                 default:
  352.                 {
  353.                     SetIoErr(ERROR_BAD_HUNK);
  354.                     Success=FALSE;
  355.                     break;
  356.                 }
  357.             }
  358.             
  359.             if (Success)
  360.             {
  361.                 /* XOR Delta decrunching */
  362.                 if (chunk->flags&FLGF_XOR_REFERENCE_INTO_DEST)
  363.                 {
  364.                     XOR_Memory(referencedata,destindata,destinsize);
  365.                 }
  366.                 
  367.                 /* Now finally implemented: recursive decrunching */
  368.                 if (chunk->flags&FLGF_USE_EXTRA_BUFFER)
  369.                 {
  370.                     Success=DecrunchBitmap(cb,o,destindata,destinsize,bm,bmhd,modeid);
  371.                 }
  372.                 
  373.                 /* Here we examine the DeBoxInfo structure and create a Bitmap */
  374.                 if (*bm==NULL && Extra)
  375.                 {
  376.                     struct DeBoxInfo *info=(struct DeBoxInfo*)destindata;
  377.                     
  378.                     /* Fill in the size information */
  379.                     bmhd->bmh_Width  = bmhd->bmh_PageWidth  = info->width;
  380.                     bmhd->bmh_Height = bmhd->bmh_PageHeight = info->height;
  381.                     bmhd->bmh_Depth  = info->depth;
  382.                     
  383.                     /* Compute the mode ID */
  384.                     *modeid = info->modeid & (HIRES|HAM|EXTRA_HALFBRITE|SUPERHIRES|DOUBLESCAN|LACE);
  385.                     
  386. //                    Message(cb,    "Width: %ld\n"
  387. //                                "Height: %ld\n"
  388. //                                "Depth: %ld\n"
  389. //                                "Colors: %ld\n"
  390. //                                "ModeID: %04lx",
  391. //                                (ULONG)bmhd->bmh_Width,
  392. //                                (ULONG)bmhd->bmh_Height,
  393. //                                (ULONG)bmhd->bmh_Depth,
  394. //                                (ULONG)info->numcolors,
  395. //                                (ULONG)*modeid);
  396.                     
  397.                     /* Set the number of colors */
  398.                     setdtattrs (cb, o, PDTA_NumColors, info->numcolors, TAG_DONE);
  399.                     
  400.                     /* Get the destination for the color information */
  401.                     getdtattrs (cb, o,
  402.                         PDTA_ColorRegisters, (ULONG)&cmap,
  403.                         PDTA_CRegs, &cregs,
  404.                         TAG_DONE);
  405.                     
  406.                     /* Get pointer to palette array */
  407.                     colors=(UWORD*)((UBYTE*)(info)+info->palette_offset);
  408.                     
  409.                     /* Set the color information */
  410.                     for (n=0; n < info->numcolors; n++)
  411.                     {
  412.                         /* Set the master color table */
  413.                         cmap->red = ((*colors&0xF00)>>4)|((*colors&0xF00)>>8);
  414.                         cmap->green=((*colors&0x0F0)   )|((*colors&0x0F0)>>4);
  415.                         cmap->blue =((*colors&0x00F)<<4)|((*colors&0x00F)   );
  416.                         
  417.                         /* Set the color table used for remapping */
  418.                         cregs[n * 3 + 0] = cmap->red   << 24;
  419.                         cregs[n * 3 + 1] = cmap->green << 24;
  420.                         cregs[n * 3 + 2] = cmap->blue  << 24;
  421.                         
  422.                         colors++;
  423.                         cmap++;
  424.                     }
  425.                     
  426.                     /* Allocate the bitmap */
  427.                     if (!(*bm = AllocBitMap (bmhd->bmh_Width, bmhd->bmh_Height, bmhd->bmh_Depth, BMF_CLEAR, NULL)))
  428.                     {
  429.                         SetIoErr(ERROR_NO_FREE_STORE);
  430.                         Success=FALSE;
  431.                         break;
  432.                     }
  433.                     
  434.                     /* Allow further chunk processing */
  435.                     chunk->flags|=FLGF_ANOTHER_CHUNK_FOLLOWS;
  436.                 }
  437.                 
  438.                 /* Free any existing extra buffers */
  439.                 if (Extra)
  440.                 {
  441.                     FreeVec(destindata);
  442.                     Extra=FALSE;
  443.                 }
  444.             }
  445.             
  446.             /* See if some more chunks will follow */
  447.             if (!(chunk->flags&FLGF_ANOTHER_CHUNK_FOLLOWS))
  448.             {
  449.                 break;
  450.             }
  451.         }
  452.     }
  453.     /* Just in case we broke out of the loop */
  454.     /* Free any existing extra buffers */
  455.     if (Extra)
  456.     {
  457.         FreeVec(destindata);
  458.         Extra=FALSE;
  459.     }
  460.     return(Success);
  461. }
  462.